<script lang="ts" setup>
import type { UploadFile, UploadProps } from 'ant-design-vue'

import type { VxeGridListeners, VxeTableGridOptions } from '#/adapter/vxe-table'
import type { scmGoodsData } from '#/views/backend/scmGoods/config'

import { onMounted, onUnmounted, ref, watch } from 'vue'

import { alert, Page, useVbenModal } from '@vben/common-ui'
import { useAccessStore } from '@vben/stores'

import { Button, Image, ImagePreviewGroup, Input, message, Popconfirm, Popover, Space, Upload } from 'ant-design-vue'
import jsSHA from 'jssha'

import { useVbenVxeGrid } from '#/adapter/vxe-table'
import { getUserBaseApi, QiniuCallback } from '#/api'
import { allIndex, getScmGoodsList, getTreeAll, goodsExcelOut, goodsIngrImages, setStatus, syncErp } from '#/api/goods/scmGoods'
import { completeCategoryPaths, completePaths, getUrl, uuid } from '#/utils'
import { scmGoodColumns } from '#/views/backend/scmGoods/config'

import indexModel from '../../backend/batchOrdering/indexModel.vue'
import ScmGooDetail from './modules/scmGooDetail.vue'

const categoryOptions = ref([]) // 货品分类树
const timeCategoryOptions = ref([]) // 货品波段树

const formOptions: any = {
  collapsed: true,
  submitOnChange: false,
  // 按下回车时是否提交表单
  submitOnEnter: true,
  wrapperClass: 'grid-cols-5',

  layout: 'horizontal',
  schema: [
    {
      component: 'Input',
      componentProps: {
        placeholder: '模糊搜索',
        allowClear: true,
      },
      fieldName: 't_template_no',
      label: '简码',
      operator: 'LIKE',
    },
    {
      component: 'Cascader',
      fieldName: 'category',
      label: '货品分类',
      // 调整货品分类的宽度
      componentProps: {
        options: categoryOptions,
        placeholder: '请选择',
        showSearch: true,
        allowClear: true,
        multiple: true,
      },
      operator: '123',
    },
    {
      component: 'Cascader',
      fieldName: 'timeCategory',
      label: '货品波段',
      // 调整货品波段的宽度
      componentProps: {
        options: timeCategoryOptions,
        placeholder: '货品波段',
        showSearch: true,
        allowClear: true,
        multiple: true,
        operator: '123',
      },
    },
    {
      component: 'Input',
      componentProps: {
        placeholder: '请输入',
        allowClear: true,
      },
      fieldName: 'goods_no',
      label: '货号',
      // 调整货号的宽度
      operator: '=',
    },
    {
      component: 'Select',
      componentProps: {
        allowClear: true,
        filterOption: true,
        options: [
          {
            label: '禁用',
            value: '0',
          },
          {
            label: '启用',
            value: '1',
          },
        ],
        placeholder: '状态',
        showSearch: true,
      },
      operator: '=',
      fieldName: 'status',
      render: 'tag',
      label: '状态',
      // 调整状态的宽度
    },
    {
      component: 'Select',
      componentProps: {
        allowClear: true,
        filterOption: true,
        options: [
          {
            label: '待同步',
            value: '0',
          },
          {
            label: '已同步',
            value: '1',
          },
        ],
        placeholder: '同步',
        showSearch: true,
      },
      operator: '=',
      fieldName: 'erp_status',
      label: '同步',
      // 调整同步的宽度
    },
    {
      component: 'Input',
      componentProps: {
        placeholder: '模糊搜索',
        allowClear: true,
      },
      fieldName: 'goods_name',
      label: '品名',
      // 调整品名的宽度
      operator: 'LIKE',
    },
    {
      component: 'Input',
      componentProps: {
        placeholder: '模糊搜索',
        allowClear: true,
      },
      fieldName: 'sale_price',
      label: '零售价',
      // 调整零售价的宽度
      operator: '=',
    },
    {
      component: 'Input',
      componentProps: {
        placeholder: '采购价',
        allowClear: true,
      },
      fieldName: 'purchase_price',
      label: '采购价',
      // 调整采购价的宽度
      operator: '=',
    },
    {
      component: 'Input',
      componentProps: {
        placeholder: '分销价',
        allowClear: true,
      },
      fieldName: 'distribution_price',
      label: '分销价',
      // 调整分销价的宽度
      operator: '=',
    },
    {
      component: 'Input',
      componentProps: {
        placeholder: '跟单',
        allowClear: true,
      },
      fieldName: 'merchandiser',
      label: '跟单',
      operator: '=',
    },
    {
      component: 'Input',
      componentProps: {
        placeholder: '买手',
        allowClear: true,
      },
      fieldName: 'buyer',
      label: '买手',
      operator: '=',
    },
    {
      component: 'RangePicker',
      componentProps: {
        placeholder: ['开始时间', '结束时间'],
        style: { width: '100%' },
        format: 'YYYY-MM-DD HH:mm:ss',
        valueFormat: 'YYYY-MM-DD HH:mm:ss',
      },
      fieldName: 'created_at',
      label: '创建时间',
      operator: 'RANGE',
    },
  ],
  // 是否可展开
  showCollapseButton: true,
  submitButtonOptions: {
    content: '查询',
  },
}

const gridOptions: VxeTableGridOptions<scmGoodsData> = {
  checkboxConfig: {
    highlight: true,
    labelField: 'name',
    trigger: 'row',
  },
  height: 'auto',
  columns: scmGoodColumns,
  exportConfig: {},
  keepSource: true,
  proxyConfig: {
    ajax: {
      query: async ({ page }, formValues) => {
        // 1. 过滤空值
        const search: any[] = []
        for (const [key, value] of Object.entries(formValues)) {
          if (value === null || value === '' || value === undefined) continue
          const fieldSchema = formOptions.schema.find((i: any) => i.fieldName === key)
          let field = key
          const specialMappings: Record<string, string> = {
            t_template_no: 'template.template_no',
          }
          // 只转换特殊映射中明确指定的字段
          if (specialMappings[key]) {
            field = specialMappings[key]
          }
          // 处理特殊字段格式
          let fieldValue = value
          // 处理created_at时间范围格式
          if (key === 'created_at' && Array.isArray(value) && value.length === 2) {
            // 将日期范围数组转换为字符串格式："开始时间,结束时间"
            fieldValue = value.join(',')
          }
          if (key === 'timeCategory') {
            fieldValue = completePaths(value, timeCategoryOptions.value)
          }
          if (key === 'category') {
            fieldValue = completeCategoryPaths(value, categoryOptions.value)
          }

          search.push({
            field,
            val: fieldValue,
            operator: fieldSchema?.operator,
            render: fieldSchema?.render,
          })
        }
        // 2. 调接口
        const res = await getScmGoodsList({
          page: page.currentPage,
          limit: page.pageSize,
          search,
          order: 'goods_id,desc',
          quick_search: quick_search.value,
        })
        currentFormValues.value = {
          search,
          order: 'goods_id,desc',
          quick_search: quick_search.value,
        }
        return { items: res.list, total: res.total }
      },
    },
    sort: true,
  },
  toolbarConfig: {
    search: true,
    custom: true,
    export: true,
    // import: true,
    refresh: true,
    zoom: true,
  },
  id: 'scm_goods_list',
  customConfig: {
    storage: true,
  },
}

onMounted(async () => {
  const cateRes = await allIndex()
  categoryOptions.value = cateRes.list
  const timeRes = await getTreeAll()
  timeCategoryOptions.value = timeRes
})
// 双击打开编辑
const gridEvents: VxeGridListeners = {
  cellDblclick: ({ row }) => {
    openModal(row, 'edit')
  },
}
const [Grid, gridApi] = useVbenVxeGrid({ formOptions, gridOptions, gridEvents })

// 存储拷贝按钮的禁用状态
const isCopyDisabled = ref(true)

const isEditDisabled = ref(true)

// 检查并更新拷贝按钮状态
function checkCopyButtonStatus() {
  try {
    if (gridApi?.grid?.getCheckboxRecords) {
      const selectedRecords = gridApi.grid.getCheckboxRecords()
      // 只有选中且只选中一条记录时，才启用拷贝按钮
      isCopyDisabled.value = !selectedRecords || selectedRecords.length !== 1
      // 多选时
      isEditDisabled.value = !selectedRecords || selectedRecords.length === 0
    } else {
      isCopyDisabled.value = true
      isEditDisabled.value = true
    }
  } catch (error) {
    console.error('检查选中记录时出错:', error)
    isCopyDisabled.value = true
    isEditDisabled.value = true
  }
}

// 使用watch监听gridApi的变化
watch(
  () => gridApi?.grid,
  (newGrid) => {
    if (newGrid) {
      // 当grid可用时，立即检查一次状态
      checkCopyButtonStatus()
      // 设置一个定时器定期检查选中状态变化
      const interval = setInterval(() => {
        if (gridApi?.grid) {
          checkCopyButtonStatus()
        }
      }, 300) // 每300ms检查一次
      // 组件卸载时清除定时器
      onUnmounted(() => {
        clearInterval(interval)
      })
    }
  },
  { immediate: true },
)

// 在数据刷新后重新检查选中状态
function onRefresh() {
  gridApi.query()
  // 延迟检查，确保数据已刷新完成
  setTimeout(checkCopyButtonStatus, 500)
}
/**
 *  停用启用
 */
async function toggleGoodsStatus(row: any) {
  const hideLoading = message.loading({
    content: `${row.status === 0 ? '正在启用' : '正在禁用'} ${row.goods_name}`,
    duration: 3,
  })
  setStatus({ id: row.goods_id })
    .then(() => {
      message.success({
        content: `${row.status === 0 ? '成功启用' : '成功禁用'} ${row.goods_name}`,
      })
      hideLoading()
      onRefresh()
    })
    .catch(() => {
      hideLoading()
    })
}

/**
 *  推送erp
 */
async function pushErp(row: any) {
  const hideLoading = message.loading({
    content: `正在推送'${row.goods_name}`,
    duration: 3,
  })
  syncErp({ goods_id: row.goods_id }).then((res) => {
      if (res.data.code === 0) {
        message.error(res.data.msg)
      } else if (res.data.code === 1) {
        message.success({
          content: ` '推送成功'${row.goods_name}`,
        })
      }
      hideLoading()
      onRefresh()
    })
    .catch(() => {
      hideLoading()
    })
}

/**
 *  快速查询查询
 */
const quick_search = ref()
function doSearch() {
  gridApi.query()
}

/**
 * 导出
 */
const currentFormValues: any = ref()
function handExcel() {
  if (currentFormValues.value.search.length === 0 && currentFormValues.value.quick_search === undefined) {
    message.error({ content: '需要筛选条件' })
  } else {
    goodsExcelOut(currentFormValues.value).then((res: any) => {
      window.open(res.path)
    })
  }
}

/**
 * 导出检测报告
 */
function handFilesZip() {
  if (currentFormValues.value.search.length === 0 && currentFormValues.value.quick_search === undefined) {
    message.error({ content: '需要筛选条件' })
  } else {
    goodsIngrImages(currentFormValues.value).then((res: any) => {
      window.open(res)
    })
  }
}
const [DetailModal, DetailModalApi] = useVbenModal({
  connectedComponent: ScmGooDetail,
})

// 单独编辑
function openModal(res: any, but: string) {
  DetailModalApi.setData({
    ids: res.goods_id,
    view: but,
  }).open()
}
// 多个编辑
function openModals() {
  const data: any = gridApi.grid.getCheckboxRecords()
  const goodsIds = data.map((item: any) => item.goods_id)
  DetailModalApi.setData({
    ids: goodsIds,
    view: 'edit',
  }).open()
}

function copy() {
  const data: any = gridApi.grid.getCheckboxRecords()
  DetailModalApi.setData({
    ids: data[0].goods_id,
    view: 'copy',
  }).open()
}

const siteConfigData = ref()
// 获取上传配置

// 上传配置类型定义
interface UploadConfig {
  maxsize: number
  savename: string
  mimetype: string
  url: string
  token: string
  mode: string
}
const getUploadConfig = async (): Promise<UploadConfig> => {
  const { siteConfig } = await getUserBaseApi()
  siteConfigData.value = siteConfig
  return siteConfig.upload
}
// 计算文件SHA1哈希值
async function getFileSha1(file: File): Promise<string> {
  const shaObj = new jsSHA('SHA-1', 'ARRAYBUFFER')
  shaObj.update(await file.arrayBuffer())
  return shaObj.getHash('HEX')
}
// 自定义上传方法
const customRequest: UploadProps['customRequest'] = async ({ file, onError, onProgress, onSuccess }) => {
  try {
    // 1. 获取上传配置
    onProgress?.({ percent: 0 })
    message.loading('正在获取上传配置...')

    const uploadConfig = await getUploadConfig()

    // 2. 检查文件类型是否符合配置
    const allowedTypes = uploadConfig.mimetype.split(',')
    const fileExtension = file.name.split('.').pop()?.toLowerCase() || ''
    if (!allowedTypes.includes(fileExtension)) {
      throw new Error(`不支持的文件类型，仅支持${uploadConfig.mimetype}`)
    }

    // 3. 检查文件大小是否符合配置
    if (file.size > uploadConfig.maxsize) {
      throw new Error(`文件大小不能超过${(uploadConfig.maxsize / 1024 / 1024).toFixed(2)}MB`)
    }

    // 4. 计算文件SHA1并生成key
    onProgress?.({ percent: 10 })
    message.loading('正在处理文件...')

    // 计算文件SHA1哈希值
    const sha1 = await getFileSha1(file)

    // 根据savename模板生成文件key

    // 5. 构造上传表单数据
    const formData = new FormData()
    formData.append('file', file)
    formData.append('token', uploadConfig.token)
    formData.append('key', `scm/goods_tem/${file.name}`) // 添加key字段，与旧代码保持一致

    // 生成uuid并作为查询参数添加到URL中（按照旧代码的params方式）
    const fileUuid = uuid()

    // 6. 执行上传
    const xhr = new XMLHttpRequest()

    xhr.upload.addEventListener('progress', (e) => {
      if (e.total > 0) {
        const percent = Math.round((e.loaded / e.total) * 100)
        onProgress?.({ percent })
      }
    })

    xhr.addEventListener('load', async () => {
      if (xhr.status >= 200 && xhr.status < 300) {
        try {
          const response = JSON.parse(xhr.responseText)
          // 调用QiniuCallback接口，并传入上传返回的数据
          try {
            const callbackData = {
              url: response.key,
              sha1,
              name: file.name,
              size: file.size,
              type: file.type,
            }
            await QiniuCallback(callbackData)
          } catch (callbackError) {
            console.error('QiniuCallback调用失败:', callbackError)
          }
          onSuccess?.(response, file)
          // 注意：不再手动维护uploadedKeys数组，而是通过handleChange统一处理
        } catch {
          onError?.(new Error('上传成功但解析响应失败'))
        }
      } else {
        onError?.(new Error(`上传失败: ${xhr.statusText}`))
      }
    })

    xhr.addEventListener('error', () => {
      onError?.(new Error('上传过程中发生错误'))
    })

    // 将uuid作为查询参数添加到URL中
    const urlWithParams = new URL(uploadConfig.url)
    urlWithParams.searchParams.append('uuid', fileUuid)

    xhr.open('POST', urlWithParams.toString())
    xhr.send(formData)

    message.destroy()
  } catch (error) {
    message.destroy()
    message.error(error instanceof Error ? error.message : '上传失败')
    onError?.(error instanceof Error ? error : new Error(String(error)))
  }
}
const fileList = ref<UploadFile[]>([])

const [indexModal, indexModalApi] = useVbenModal({
  connectedComponent: indexModel,
})
function openBatchs() {
  indexModalApi.setData({ data: gridApi.grid.getCheckboxRecords() }).open()
}
function openBatch(data: any) {
  indexModalApi.setData({ data: [data] }).open()
}

// 导入文件列表
const fileList1 = ref<any[]>([])
// 上传组件引用
const uploadRef = ref()
// 处理导入成功回调，检查业务逻辑是否成功
const handleImportSuccess = (response: any, file: any, fileList1: any[]) => {
  if (response.code === 1) {
    message.success('导入成功', 5)
    alert({
      content: response.msg,
      icon: 'success',
    })
  } else {
    alert({
      content: response.msg,
      icon: 'error',
    })
  }
}
const accessStore = useAccessStore()
const customHeaders = {
  batoken: accessStore.accessToken ?? '',
  'X-Requested-With': 'XMLHttpRequest',
}

const getDownload = () => {
  const dom = document.createElement('a')
  const url = `${getUrl()}/static/template/货品档案导入或下单模版..xlsx`
  dom.setAttribute('href', url)
  dom.setAttribute('download', '货品档案导入或下单模版.xlsx')
  dom.click()
}
</script>

<template>
  <Page auto-content-height>
    <indexModal />
    <Grid>
      <template #toolbar-actions>
        <Space>
          <Button type="primary" @click="openModal([], 'add')">新建</Button>
          <Button type="primary" :disabled="isEditDisabled" @click="openModals()">编辑</Button>
          <Button type="primary" :disabled="isCopyDisabled" @click="copy()">拷贝</Button>
          <Button type="primary" @click="handExcel">导出</Button>
          <Button type="primary" @click="handFilesZip">导出检测报告</Button>
          <Popover content="货号图片必须以货号命名" da trigger="hover">
            <Upload ref="uploadRef" :custom-request="customRequest" :file-list="fileList" :multiple="false" accept=".jpg,.png" :show-upload-list="false">
              <Button type="primary" danger>批量上传货号图片</Button>
            </Upload>
          </Popover>
          <Button type="primary" @click="openBatchs">需求提报</Button>

          <Upload
            ref="uploadRef"
            :headers="customHeaders"
            :action="`${getUrl()}/admin/v2.Goods/batchImportGoodsAndPurchase`"
            :on-success="handleImportSuccess"
            :file-list="fileList1"
            :multiple="false"
            accept=".xlsx,.xls"
            :show-upload-list="false"
          >
            <template #default>
              <Button type="primary">批量导入成品档案或并下单</Button>
            </template>
          </Upload>
          <Button type="primary" @click="getDownload">下载导入模板</Button>
        </Space>
      </template>
      <template #toolbar-tools>
        <Input v-model:value="quick_search" allow-clear placeholder="通过简码、货号、品名模糊搜索" style="width: 200px; margin-right: 8px" @change="doSearch" />
      </template>

      <template #imgs="{ row }">
        <ImagePreviewGroup>
          <template v-for="item in row.goods_images" :key="item">
            <Image :src="item" />
          </template>
        </ImagePreviewGroup>
      </template>

      <template #action="{ row }">
        <Space>
          <Popconfirm :title="row.status === 0 ? '确认启用该产品吗？' : '确认禁用该产品吗？'" ok-text="确认" cancel-text="取消" @confirm="toggleGoodsStatus(row)">
            <Button title="修改状态：启用状态或禁用状态" type="primary" class="my-yello-btn" size="small">
              {{ row.status === 0 ? '启用' : '禁用' }}
            </Button>
          </Popconfirm>
          <Popconfirm title="确定要推送到ERP系统吗" ok-text="确认" cancel-text="取消" @confirm="pushErp(row)">
            <Button type="primary" title="添加数据到ERP系统的货品档案" class="my-green-btn" size="small">推送</Button>
          </Popconfirm>
          <Button type="primary" size="small" @click="openModal(row, 'edit')">编辑</Button>
          <Button type="primary" size="small" @click="openBatch(row)">提报</Button>
        </Space>
      </template>
    </Grid>
    <DetailModal @refresh="gridApi.reload()" />
  </Page>
</template>
<style lang="scss" scoped>
.my-green-btn.ant-btn-primary {
  background-color: #67c23a;
  border-color: #67c23a;
}

.my-yello-btn.ant-btn-primary {
  background-color: #e6a23c;
  border-color: #e6a23c;
}
</style>
